package com.term.util.zxing;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.term.util.encryption.EncryptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Hashtable;

/**
 * Created by chenGang on 2016/12/29.
 * 二维码生成工具
 */
@Component
public class ZxingUtils {


    public static String doEncode(String contents, int width, int height, int margin) {
//        File file = new File("C:/Users/tony1/Desktop/test.png");
        String code = null;
        try {
            BitMatrix bitMatrix = createQrcode(contents,width,height);
            bitMatrix = deleteWhite(bitMatrix,margin);
            BufferedImage qrCode = MatrixToImageWriter.toBufferedImage(bitMatrix);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(qrCode, "png", outputStream);
            code = new String(EncryptionUtils.base64(outputStream.toByteArray()));
//            MatrixToImageWriter.writeToPath(bitMatrix, "png", file.toPath());
//            System.out.println(code);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;
    }

    public static String encode(String contents, int width, int height){
        return doEncode(contents,width,height, 20);
    }

    public static byte[] encodeAndLogo(String contents,String logoUrl, int width, int height){
        try {
            //生成二维码
            BitMatrix bitMatrix = createQrcode(contents,width,height);
            //去除白边
            bitMatrix = deleteWhite(bitMatrix,20);
//            int[] result = changeColor(bitMatrix);
            MatrixToImageConfig config = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
            BufferedImage qrcode = MatrixToImageWriter.toBufferedImage(bitMatrix, config);
            //去除白边后放大二维码
            qrcode = zoomInImage(qrcode,width,height);
            int logoWidth = qrcode.getWidth()/5*1;   //设置logo图片宽度为二维码图片的五分之一
            int logoHeight = qrcode.getHeight()/5*1; //设置logo图片高度为二维码图片的五分之一
            int logoX = (qrcode.getWidth()-logoWidth)/2;   //设置logo图片的位置,这里令其居中
            int logoY = (qrcode.getHeight()-logoHeight)/2; //设置logo图片的位置,这里令其居中
            if (logoUrl != null && !logoUrl.isEmpty()){
                Graphics2D graphics2D = qrcode.createGraphics();
                graphics2D.drawImage(ImageIO.read(new File(logoUrl)), logoX, logoY, logoWidth, logoHeight, null);
                graphics2D.dispose();
            }
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(qrcode, "png", outputStream);
            return outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static BitMatrix createQrcode(String contents, int width, int height) throws WriterException {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 指定编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        return new MultiFormatWriter().encode(contents,
                BarcodeFormat.QR_CODE, width, height, hints);
    }

    /**
     * 改变二维码颜色
     * @param bitMatrix
     * @return
     */
    public static int[] changeColor(BitMatrix bitMatrix){
        int red = 0xFF0000;
        int white = 0xFFFFFFFF;
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                pixels[y * width + x] = bitMatrix.get(x, y) ? red : white;
            }
        }
        return pixels;
    }

    /**
     * 去掉二维码中多余的白边
     * @param matrix
     * @param margin
     * @return
     */
    public static BitMatrix deleteWhite(BitMatrix matrix, int margin){
        int padingMin = margin*2;
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2]+padingMin;
        int resHeight = rec[3]+padingMin;

        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth - margin; i++) {
            for (int j = 0; j < resHeight - margin; j++) {
                if (matrix.get(i-margin + rec[0], j-margin + rec[1]))
                    resMatrix.set(i, j);
            }
        }
        return resMatrix;
    }

    /**
     * 图片放大缩小
     */
    public static BufferedImage  zoomInImage(BufferedImage  originalImage, int width, int height){
        BufferedImage newImage = new BufferedImage(width,height,originalImage.getType());
        Graphics g = newImage.getGraphics();
        g.drawImage(originalImage, 0,0,width,height,null);
        g.dispose();
        return newImage;
    }
}
